//把一个数组最开始的若干个元素搬到数组的末尾，我们称之为数组的旋转。输入一个递增排序的数组的一个旋转，输出旋转数组的最小元素。例如，数组 [3,4,5,1,2
//] 为 [1,2,3,4,5] 的一个旋转，该数组的最小值为1。 
//
// 示例 1： 
//
// 输入：[3,4,5,1,2]
//输出：1
// 
//
// 示例 2： 
//
// 输入：[2,2,2,0,1]
//输出：0
// 
//
// 注意：本题与主站 154 题相同：https://leetcode-cn.com/problems/find-minimum-in-rotated-sor
//ted-array-ii/ 
// Related Topics 数组 二分查找 
// 👍 373 👎 0


package leetcode.editor.cn1;

/**
 * 二分查找，找到的数字怎么确定是最小的
 * <p>
 * 把一个数组最开始的若干个元素搬到数组的末尾，我们称之为数组的旋转。输入一个递增排序的数组的一个旋转，输出旋转数组的最小元素。
 * 例如，数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的一个旋转，该数组的最小值为1。 
 * 输入：[2,2,2,0,1]，输出：0 
 * 假设最后一个元素为x，最小值左边的元素 > x，最小值右边的元素 < x
 * 1、mi < hi，说明最小值在[lo, mi]之间
 * 2、mi > hi，说明最小值在(mi, hi]之间
 * 3、mi == hi，直接忽略最右侧端点 hi = hi - 1
 */
public class XuanZhuanShuZuDeZuiXiaoShuZiLcof_1027 {
    public static void main(String[] args) {
        Solution solution = new XuanZhuanShuZuDeZuiXiaoShuZiLcof_1027().new Solution();
        // TO TEST
        System.out.println(solution.minArray(new int[]{10, 1, 10, 10, 10}));
        System.out.println(solution.minArray(new int[]{3, 4, 5, 1, 2}));
        System.out.println(solution.minArray(new int[]{2, 2, 2, 0, 1}));
        System.out.println(solution.minArray(new int[]{3, 1, 1}));
    }

    //leetcode submit region begin(Prohibit modification and deletion)
    class Solution {
        public int minArray(int[] numbers) {
            int lo = 0, hi = numbers.length - 1, mi = -1;

            int result = -1;

            while (lo < hi) {
                mi = (lo + hi) / 2;
                if (numbers[mi] < numbers[hi]) {
                    // 说明，最小值在[lo,  mi]中间
                    hi = mi;
                } else if (numbers[mi] > numbers[hi]) {
                    // 最小值在(mi, hi]之间
                    lo = mi + 1;
                } else {
                    // 忽略二分查找的右端点
                    hi = hi - 1;
                }
            }
            return numbers[lo];
        }
    }
    //leetcode submit region end(Prohibit modification and deletion)

}
